package com.leyou.user.service;

import com.leyou.common.constants.MQConstants;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.upload.Path;
import com.leyou.common.utils.BeanHelper;
import com.leyou.user.domain.User;
import com.leyou.user.domain.UserDTO;
import com.leyou.user.mapper.UserMapper;
import net.bytebuddy.implementation.bytecode.assign.TypeCasting;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class UserService {

    @Autowired
    private UserMapper userMapper;


    //检测用户名或者手机是否在数据库存在
    public Boolean checkUsername(String data, Integer type) {
        User user = new User();
        switch(type){
            case 1:
                //用户名
                user.setUsername(data);
                break;
            case 2:
                //手机号
                user.setPhone(data);
                break;
            default:
                throw new  LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
        int count = userMapper.selectCount(user);
        //如果找到了就证明 输入的不可用 返回false
        return count != 1;
    }
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private AmqpTemplate amqpTemplate;

    //发送短信
    public void sendCode(String phone) {
        //生成一个随机的6位的验证码
        String code = RandomStringUtils.randomNumeric(6);
        //存入缓存库[String 结构]
        redisTemplate.opsForValue().set(Path.CODE_PRE+phone,code,12, TimeUnit.HOURS);
        //给mq发消息 发送短信 由于第三方的不确定性 不能采用同步方式 采用异步方式
        //如用同步方式 会认为网站太慢 实际上也是接收 第三方的短信服务器响应太慢
        //如用异步方式 会认为短信接收的速度慢而不是网站的原因 直接给出发送成功 体验好
        Map<String,String> map = new HashMap<>();
        map.put("phone",phone);
        map.put("code",code);
        amqpTemplate.convertAndSend(MQConstants.Exchange.SMS_EXCHANGE_NAME,MQConstants.RoutingKey.VERIFY_CODE_KEY,map);
    }
    
    @Autowired //加密的对象
    private BCryptPasswordEncoder passwordEncoder;

    //注册用户
    public void register(User user, String code) {
        //判断 redis是否有短信验证码
        //这是为了防止 用户直接填验证码 注册 其实也没有意义 如果没有发送短信息的话缓存库也就拿不到验证码 也会报错
        Boolean hasKey = redisTemplate.hasKey(Path.CODE_PRE + user.getPhone());
        if(!hasKey){
            throw new LyException(ExceptionEnum.INVALID_VERIFY_CODE);
        }
        //获取redis中的验证码
        String redisCode = redisTemplate.opsForValue().get(Path.CODE_PRE + user.getPhone());
        //判断页面拿到的验证码是否跟缓存库的中是否一致
        if(!StringUtils.equals(redisCode,code)){
            throw new LyException(ExceptionEnum.INVALID_VERIFY_CODE);
        }
        //用户密码加密
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        //存入
        int count = userMapper.insertSelective(user);
        if(count != 1){
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

    }

    //使用用户的账号密码查询 是否存在该用户
    public UserDTO queryUser(String username, String password) {
        //先查用户名
        User record = new User();
        record.setUsername(username);
        User user = userMapper.selectOne(record);
        if(user == null){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        //比对密码
        boolean isTrue = passwordEncoder.matches(password, user.getPassword());
        if(! isTrue){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        return BeanHelper.copyProperties(user,UserDTO.class);
    }
}
